﻿
Ext.define('Ext.ComponentManager', {
    alternateClassName: 'Ext.ComponentMgr',

    singleton: true,

    count: 0,

    typeName: 'xtype',

    constructor: function (config) {
        Ext.apply(this, config || {});
        this.all = {};
        this.references = {};
        this.onAvailableCallbacks = {};
    },


    create: function (config, defaultType) {
        if (typeof config == 'string') {
            return Ext.widget(config);
        }
        if (config.isComponent) {
            return config;
        }

        if ('xclass' in config) {
            return Ext.create(config.xclass, config);
        }

        return Ext.widget(config.xtype || defaultType, config);
    },


    get: function (id) {
        return this.all[id];
    },

    register: function (component) {
        var all = this.all,
            key = component.getId();

        if (key === undefined) {
            Ext.Error.raise('Key is undefined. Please ensure the item has a key before registering the item.');
        }
        if (key in all) {
            Ext.Error.raise('Registering duplicate id "' + key + '" with this manager');
        }

        all[key] = component;

        if (component.reference) {
            this.references[key] = component;
        }

        this.count++;

        if ((this.onAvailableCallbacks[key] || []).length) {
            this.notifyAvailable(component);
        }
    },

    unregister: function (component) {
        var id = component.getId();

        if (component.reference) {
            delete this.references[id];
        }
        delete this.all[id];

        this.count--;
    },

    markReferencesDirty: function () {
        this.referencesDirty = true;
    },

    fixReferences: function () {
        var me = this,
            references = me.references,
            key;

        if (me.referencesDirty) {
            for (key in references) {
                if (references.hasOwnProperty(key)) {
                    references[key].fixReference();
                }
            }
            me.referencesDirty = false;
        }
    },


    onAvailable: function (id, fn, scope) {
        var me = this,
            callbacks = me.onAvailableCallbacks,
            all = me.all,
            item;

        if (id in all) {
            item = all[id];
            fn.call(scope || item, item);

        } else if (id) {

            if (!Ext.isArray(callbacks[id])) {
                callbacks[id] = [];
            }
            callbacks[id].push(function (item) { fn.call(scope || item, item); });
        }
    },


    notifyAvailable: function (item) {
        var callbacks = this.onAvailableCallbacks[item && item.getId()] || [];
        while (callbacks.length) {
            (callbacks.shift())(item);
        }
    },


    each: function (fn, scope) {
        return Ext.Object.each(this.all, fn, scope);
    },


    getCount: function () {
        return this.count;
    },


    getAll: function () {
        return Ext.Object.getValues(this.all);
    },

    deprecated: {
        5: {
            methods: {

                isRegistered: null,


                registerType: null
            }
        }
    }
},
function () {

    Ext.getCmp = function (id) {
        return Ext.ComponentManager.get(id);
    };
});

